package com.starview.star.compiler.canonical.compile;

import com.starview.star.compiler.cafe.compile.HWM;
import com.starview.star.compiler.cafe.compile.ISpec;
import com.starview.star.compiler.cafe.compile.LiveMap;
import com.starview.star.compiler.util.Cons;
import com.starview.star.data.indextree.Mapping;

public class FrameState
{
  private final HWM stackHwm;
  private final LiveMap localAvail;

  private final Cons<ISpec> stackMap;
  private final Mapping<Integer, ISpec> localMap;

  public FrameState(HWM stackHwm, LiveMap localAvail, Cons<ISpec> stackMap, Mapping<Integer, ISpec> localMap)
  {
    super();
    this.stackHwm = stackHwm;
    this.localAvail = localAvail;
    this.stackMap = stackMap;
    this.localMap = localMap;
  }

  public Cons<ISpec> getStackMap()
  {
    return stackMap;
  }

  public Mapping<Integer, ISpec> getLocalMap()
  {
    return localMap;
  }

  public HWM getStackHwm()
  {
    return stackHwm;
  }

  public LiveMap getLocalAvail()
  {
    return localAvail;
  }

  public FrameState pushStack(ISpec var)
  {
    stackHwm.bump(var.slotSize());
    return new FrameState(stackHwm, localAvail, stackMap.cons(var), localMap);
  }

  public FrameState pushLocal(ISpec var)
  {
    int offset = localAvail.reserve(var.slotSize());
    return new FrameState(stackHwm, localAvail, stackMap, localMap.insrt(offset, var));
  }

  public ISpec tos()
  {
    if (!stackMap.isNil())
      return stackMap.head();
    else
      return null;
  }
}
